﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using MyBlog.Common;
using MyBlog.Model;
using Webdiyer.WebControls.Mvc;

namespace MyBlog.Web.Controllers
{
    public class BlogController : BaseController
    {
        static int _pageSize = 5;

        [TrackRequest]
        public ActionResult Index(string username)
        {
            if (string.IsNullOrWhiteSpace(username))
            {
                return Redirect("~/home/index");
            }
            var user = WebCache.GetAccount(username.Trim());
            if (null == user)
            {
                throw new ApplicationException(ErrorMsg.NotFound);
            }
            ViewBag.CurBlogUserName = this.CurBlogUserName;
            ViewBag.blogUser = WebCache.GetAccount(this.CurBlogUserID);
            ViewBag.Articles = XiaoBoKe.ArticleService.GetAll(new ArticleModel { AccountId = CurBlogUserID })
                .OrderByDescending(x => x.ReadCount)
                .ThenByDescending(x => x.ArticleCommentModels.Count)
                .ThenByDescending(x => x.IsTop).Take(10).ToList();
            ViewBag.Moods = XiaoBoKe.MoodService.GetAll(new MoodModel { AccountId = username })
                .OrderByDescending(x => x.CreateTime).Take(10).ToList();
            ViewBag.Msgs = XiaoBoKe.MessageService.GetAll(new MessageModel { AccountId = username })
                .OrderByDescending(x => x.MsgTime).Take(10).ToList();

            return View();
        }

        /// <summary>
        /// 返回博客右边公共的部分
        /// </summary>
        /// <returns></returns>
        public PartialViewResult _BlogCommonRight()
        {
            ViewBag.CurBlogUserName = this.CurBlogUserName;
            ViewBag.canEdit = this.CanEdit;
            ViewBag.blogUser = WebCache.GetAccount(CurBlogUserID);
            var allArticles = XiaoBoKe.ArticleService.GetAll(new ArticleModel { AccountId = CurBlogUserID });
            var cates = WebCache.GetCategories(CurBlogUserID).Clone();
            if (cates.Count > 0 && allArticles.Exists(x => x.CategoryModels.Count == 0))
            {
                cates.Add(new CategoryModel { ID = -1, CategoryName = "[未分类]", ArticleModels = allArticles.Where(x => x.CategoryModels.Count == 0).ToList() });
            }
            ViewBag.cates = cates;
            ViewBag.comments = XiaoBoKe.ArticleCommentService.GetAll(new ArticleCommentModel { Article = new ArticleModel { AccountId = CurBlogUserID } })
                .OrderByDescending(x => x.CommentTime).Take(15).ToList();

            var articlesGroupByDate = allArticles.GroupBy(x => new { x.CreateTime.Year, x.CreateTime.Month })
                .Select(x => new Tuple<string, int>(x.Key.Year + "年" + (x.Key.Month + "月").PadLeft(3, '0'), x.Count())).ToList();
            ViewBag.articlesGroupByDate = articlesGroupByDate;
            ViewBag.hotArticles = allArticles.Where(x => x.ReadCount > 0).OrderByDescending(x => x.ReadCount).Take(5).ToList();
            ViewBag.hotReArticles = allArticles.Where(x => x.ArticleCommentModels.Count > 0).OrderByDescending(x => x.ArticleCommentModels.Count).Take(5).ToList();
            return PartialView();
        }

        [TrackRequest]
        [Authenticate]
        public ActionResult Release(int? id)
        {
            ArticleModel article = null;
            if (id.HasValue)
            {
                article = XiaoBoKe.ArticleService.Get(id);
            }
            var cates = WebCache.GetCategories(UserSession.AccountId).Clone();
            if (cates.Count > 0 && UserSession.LoginUserInfo.ArticleModels.Exists(x => x.CategoryModels.Count == 0))
            {
                cates.Add(new CategoryModel { ID = -1, CategoryName = "[未分类]", ArticleModels = UserSession.LoginUserInfo.ArticleModels.Where(x => x.CategoryModels.Count == 0).ToList() });
            }

            ViewBag.cates = cates;
            return View(article ?? new ArticleModel());
        }

        /// <summary>
        /// 发布新的文章，需要验证
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [Authenticate]
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Release(ArticleModel model, string cids)
        {
            model.PassToIndex = UserSession.LoginUserInfo.IsAdmin;
            model.CategoryIds = string.IsNullOrWhiteSpace(cids) ? new string[] { } : cids.Split(',');
            if (model.ID > 0)
            {
                //修改
                XiaoBoKe.ArticleService.Update(model);
            }
            else
            {
                //新增
                model.AccountId = UserSession.LoginUserInfo.Account;
                model.CreateTime = model.LastUpdateTime = DateTime.Now;
                XiaoBoKe.ArticleService.Add(model);
                base.AddNotice(model.AccountId, NoticeEnum.AddArticle, ExtensionMethod.BuildLink(Url.Action("article/" + model.ID), model.Title), model.Content);
            }
            WebCache.Refresh();
            return Json(new JsonData { State = AjaxState.Success, Data = model.ID });
        }

        [Authenticate]
        public ActionResult _ArticleManager(int cid = 0, int page = 1)
        {
            var query = new ArticleModel { AccountId = UserSession.LoginUserInfo.Account, CategoryID = cid };
            var list = XiaoBoKe.ArticleService.GetAll(query).OrderByDescending(x => x.CreateTime).ToPagedList(page, _pageSize);
            ViewBag.cateId = cid;
            if (Request.IsAjaxRequest())
            {
                return PartialView("_ArticlePageList", list);
            }
            return View(list);
        }

        [Authenticate]
        public ActionResult _ArticleAjaxPageList(int cid = 0, int page = 1)
        {
            var query = new ArticleModel { AccountId = UserSession.LoginUserInfo.Account, CategoryID = cid };
            var list = XiaoBoKe.ArticleService.GetAll(query).OrderByDescending(x => x.CreateTime).ToPagedList(page, _pageSize);
            ViewBag.cateId = cid;
            if (Request.IsAjaxRequest())
            {
                return PartialView("_ArticleAjaxPageList", list);
            }
            return View(list);
        }

        /// <summary>
        /// 用户随笔首页
        /// </summary>
        /// <param name="begin"></param>
        /// <param name="end"></param>
        /// <param name="isMonth"></param>
        /// <param name="cid"></param>
        /// <param name="tagID"></param>
        /// <param name="page"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        [TrackRequest]
        //[OutputCache(Duration = 20)]
        public ActionResult Articles(DateTime? begin, DateTime? end, bool isMonth = false, int cid = 0, int tagID = 0, int page = 1, int pageSize = 10)
        {
            if (XiaoBoKe.AccountService.Get(this.CurBlogUserID) == null)
            {
                throw new ApplicationException(ErrorMsg.NotFound);
            }
            if (isMonth)
            {
                var year = begin.Value.Year;
                var month = begin.Value.Month;
                begin = DateTime.Parse(year + "-" + month + "-01");
                end = DateTime.Parse(year + "-" + month + "-" + ExtensionMethod.GetMonthDays(year, month));
            }
            var query = new ArticleModel { AccountId = CurBlogUserID, CategoryID = cid, TagID = tagID, QueryDateBegin = begin, QueryDateEnd = end };
            var articles = XiaoBoKe.ArticleService.GetAll(query).OrderByDescending(x => x.IsTop)
                .ThenByDescending(x => x.ReadCount)
                .ThenByDescending(x => x.ArticleCommentModels.Count).ToPagedList(page, pageSize);
            string tip = "随笔列表：共{0}篇".FormatStr(articles.TotalItemCount);
            if (cid != 0)//按类别查
            {
                var cate = WebCache.GetCategories(CurBlogUserID).FirstOrDefault(x => x.ID == cid);
                tip = "随笔分类：{0} 共{1}篇".FormatStr(cate == null ? "[未分类]" : cate.CategoryName, articles.TotalItemCount);
            }
            if (tagID != 0)
            {
                var tag = WebCache.GetTags(CurBlogUserID).FirstOrDefault(x => x.ID == tagID);
                tip = "当前标签：{0} 共{1}篇".FormatStr(tag == null ? "未知" : tag.TagName, articles.TotalItemCount);
            }
            if (isMonth)//按月份查
            {
                tip = begin.Value.ToString("随笔档案：yyyy年MM月  共" + articles.TotalItemCount + "篇");
            }
            ViewBag.tip = tip;
            ViewBag.begin = begin;
            ViewBag.isMonth = isMonth;
            ViewBag.cid = cid;
            ViewBag.CurBlogUserName = this.CurBlogUserName;
            ViewBag.CanEdit = CanEdit;
            return View(articles);
        }

        /// <summary>
        /// 获取文章详情
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [TrackRequest]
        public ActionResult Article(int? id)
        {
            var article = XiaoBoKe.ArticleService.Get(id);
            if (id == null || id == 0 || null == article || !CurBlogUserID.Same(article.AccountId))
            {
                throw new ApplicationException(ErrorMsg.NotFound);
            }
            if (!article.AllowAnonymous && UserSession.LoginUserInfo == null)
            {
                throw new ApplicationException(ErrorMsg.NotAllowAnonymous);
            }
            ViewBag.CanEdit = this.CanEdit;
            ViewBag.PrevAndNext = WebCache.GetArticlePrevAndNext(CurBlogUserID, id.Value);
            //增加阅读量
            var clientinfo = UserSession.GetClientInfoMD5<ArticleModel>(id.ToString() + UserSession.AccountId);
            if (CookieHelper.GetCookie(clientinfo) == null)
            {
                HttpCookie cookie = new HttpCookie(clientinfo, clientinfo);
                cookie.Expires = DateTime.Now.AddHours(12);
                CookieHelper.AddCookie(cookie);
                XiaoBoKe.ArticleService.AddReadOrAgreeCount(id.Value, ArticleDo.Read);
                article.ReadCount++;
                WebCache.Refresh(false, CurBlogUserID);
            }
            return View(article);
        }

        public PartialViewResult _CommentManager(int aid, int page = 1)
        {
            var list = new List<ArticleCommentModel>();
            list = XiaoBoKe.ArticleCommentService.GetAll(new ArticleCommentModel { ArticleId = aid })
           .Where(x => x.Parent == null).OrderByDescending(x => x.CommentTime).ToPagedList(page, 10);
            ViewBag.CanEdit = CanEdit;
            return PartialView(list);
        }

        [Authenticate(false)]
        public JsonResult DelRpComment(int id)
        {
            XiaoBoKe.ArticleCommentService.Delete(id);
            return Json(new JsonData { State = AjaxState.Success });
        }

        [Authenticate(false)]
        public JsonResult DelComment(int id)
        {
            var comments = XiaoBoKe.ArticleCommentService.GetAll(new ArticleCommentModel { ParentID = id });
            if (comments.Count > 0)
            {
                DelRpComments(comments);
            }
            XiaoBoKe.ArticleCommentService.Delete(id);
            return Json(new JsonData { State = AjaxState.Success });
        }

        void DelRpComments(List<ArticleCommentModel> items)
        {
            foreach (var item in items)
            {
                if (item.ArticleCommentModels.Count > 0)
                {
                    DelRpComments(item.ArticleCommentModels);
                }
                if (XiaoBoKe.ArticleCommentService.Get(item.ID) != null)
                {
                    XiaoBoKe.ArticleCommentService.Delete(item.ID);
                }
            }
        }

        [Authenticate(false)]
        [HttpPost]
        public JsonResult SendComment(int? pid, int aid, string content)
        {
            var comment = new ArticleCommentModel
            {
                ParentID = (pid == 0 ? null : pid),
                ArticleId = aid,
                Content = content,
                VisitorIP = UserSession.GetClientIP(),
                CommentUid = UserSession.AccountId,
                CommentTime = DateTime.Now
            };
            XiaoBoKe.ArticleCommentService.Add(comment);
            var article = WebCache.GetArticles(CurBlogUserID).First(x => x.ID == aid);
            base.AddNotice(UserSession.AccountId, NoticeEnum.CommentArticle, ExtensionMethod.BuildLink(Url.Action("article/" + aid), article.Title), content);
            try
            {
                if (!article.AccountId.Same(UserSession.AccountId))
                {
                    var notice = WebCache.GetNickName(UserSession.AccountId) + "评论了你的文章《" + article.Title + "》：" + content.StripHTML();
                    EmailHelper.SendMail(article.Account.Email, "小博客评论通知", notice);
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog("发送文章评论通知出错：" + ex.Message);
            }
            WebCache.Refresh();
            return Json(new JsonData { State = AjaxState.Success });
        }

        [Authenticate(false)]
        public JsonResult ReplyComment(int? pid, int aid, string content)
        {
            var rp = new ArticleCommentModel { ParentID = (pid == 0 ? null : pid), ArticleId = aid, Content = content, CommentTime = DateTime.Now, CommentUid = UserSession.LoginUserInfo.Account };
            XiaoBoKe.ArticleCommentService.Add(rp);
            var article = WebCache.GetArticles(CurBlogUserID).First(x => x.ID == aid);
            var comm = article.ArticleCommentModels.First(x => x.ID == pid);
            base.AddNotice(UserSession.AccountId, NoticeEnum.ReplyArticle, ExtensionMethod.BuildLink(Url.Action("article/" + aid), comm.Content), content);
            try
            {
                var item = XiaoBoKe.ArticleCommentService.Get(pid);
                if (!item.CommentUid.Same(UserSession.AccountId))
                {
                    var notice = WebCache.GetNickName(UserSession.AccountId) + "评论了你的文章《" + article.Title + "》：" + content.StripHTML();
                    EmailHelper.SendMail(article.Account.Email, "小博客评论通知", notice);
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog("发送文章评论通知出错：" + ex.Message);
            }
            return Json(new JsonData { Data = rp.ID, State = AjaxState.Success });
        }

        [Authenticate]
        public ActionResult DeleteArticle(int? id)
        {
            if (id.HasValue)
            {
                var article = XiaoBoKe.ArticleService.Get(id);
                if (article.ArticleCommentModels.Count > 0)
                {
                    foreach (var item in article.ArticleCommentModels)
                    {
                        XiaoBoKe.ArticleCommentService.Delete(item.ID);
                    }
                }
                XiaoBoKe.ArticleService.Delete(id);
                WebCache.Refresh();
                return Json(new JsonData { State = AjaxState.Success }, JsonRequestBehavior.AllowGet);
            }
            return Json(new JsonData { State = AjaxState.Fail, Message = "文章不存在，请刷新后重试!" }, JsonRequestBehavior.AllowGet);
        }

        [Authenticate(false)]
        [HttpPost]
        public JsonResult AgreeComment(int id)
        {
            var model = XiaoBoKe.ArticleCommentService.Get(id);
            if (string.IsNullOrWhiteSpace(model.AgreeUsers) || (!string.IsNullOrWhiteSpace(model.AgreeUsers) && !model.AgreeUsers.Contains(UserSession.AccountId)))
            {
                XiaoBoKe.ArticleCommentService.AddAgree(id, UserSession.AccountId);
                return Json(new JsonData { State = AjaxState.Success });
            }
            else
            {
                return Json(new JsonData { State = AjaxState.Fail, Message = "你已经点过赞啦！" });
            }
        }

        [Authenticate(false)]
        [HttpPost]
        public JsonResult AgreeArticle(int id)
        {
            var model = XiaoBoKe.ArticleService.Get(id);
            if (string.IsNullOrWhiteSpace(model.AgreeUsers) || (!string.IsNullOrWhiteSpace(model.AgreeUsers) && !model.AgreeUsers.Contains(UserSession.AccountId)))
            {
                XiaoBoKe.ArticleService.AddAgree(id, UserSession.AccountId);
                return Json(new JsonData { State = AjaxState.Success });
            }
            else
            {
                return Json(new JsonData { State = AjaxState.Fail, Message = "你已经点过赞啦！" });
            }
        }

        /// <summary>
        /// 关于博主的信息
        /// </summary>
        /// <returns></returns>
        [TrackRequest]
        public ActionResult AboutMe()
        {
            var blogUser = WebCache.GetAccount(CurBlogUserID);
            return View(blogUser);
        }

        [TrackRequest]
        [Authenticate]
        public ActionResult UserInfo()
        {
            var account = XiaoBoKe.AccountService.Get(base.CurBlogUserID);
            return View(account);
        }

        [HttpPost]
        [Authenticate]
        public ActionResult UpdateUserInfo(AccountModel model)
        {
            XiaoBoKe.AccountService.Update(model);
            UserSession.Refresh();
            WebCache.Refresh();
            return Json(new JsonData { State = AjaxState.Success });
        }

        [Authenticate]
        public ActionResult UploadUserHead(string account)
        {
            var img = System.Web.HttpContext.Current.Request.Files[0];
            var byts = img.InputStream.GetImageBytes();
            var head = new HeaderModel { ImageContent = byts, Size = byts.Length / 1024 + "KB", ContentType = img.ContentType };
            XiaoBoKe.AccountService.UploadUserHead(account, head);
            WebCache.Refresh();
            Thread.Sleep(2000);
            return Json(new JsonData { State = AjaxState.Success }, "text/html");
        }

        public ActionResult GetUserHead()
        {
            var user = WebCache.GetAccount(this.CurBlogUserID);
            var bytes = user.HeadId.HasValue ? user.Header.ImageContent : ExtensionMethod.GetDefaultHeadBytes();
            string contentType = user.HeadId.HasValue ? user.Header.ContentType : "jpg";
            return File(bytes, contentType);
        }

        [Authenticate]
        public PartialViewResult _LoadCategory()
        {
            var cates = WebCache.GetCategories(UserSession.LoginUserInfo.Account);
            ViewBag.Cates = cates.OrderBy(x => x.CategoryName).ToList();
            return PartialView();
        }

        [Authenticate]
        public PartialViewResult _LoadArticleCategory(string ids)
        {
            var cates = WebCache.GetCategories(UserSession.LoginUserInfo.Account);
            ViewBag.Cates = cates.OrderBy(x => x.CategoryName).ToList();
            ViewBag.ids = string.IsNullOrWhiteSpace(ids) ? null : ids.Split(',').ToList();
            return PartialView();
        }

        [Authenticate]
        [HttpPost]
        public ActionResult AddCategory(CategoryModel model)
        {
            model.AccountId = UserSession.LoginUserInfo.Account;
            if (XiaoBoKe.CategoryService.Get(model) != null)
            {
                return Json(new JsonData { State = AjaxState.Fail, Message = "类别名称已经存在啦！" });
            }
            XiaoBoKe.CategoryService.Add(model);
            WebCache.Refresh();
            return Json(new JsonData { State = AjaxState.Success });
        }

        [Authenticate]
        [HttpPost]
        public ActionResult EditCategory(int id, string newName)
        {
            var cate = new CategoryModel { ID = id, CategoryName = newName, AccountId = UserSession.LoginUserInfo.Account };
            var exist = XiaoBoKe.CategoryService.GetAll(new CategoryModel { CategoryName = newName, AccountId = UserSession.LoginUserInfo.Account })
                .Where(x => x.ID != id);
            if (exist.Count() > 0)
            {
                return Json(new JsonData { State = AjaxState.Fail, Message = "类别名称已经存在拉" });
            }
            XiaoBoKe.CategoryService.Update(cate);
            WebCache.Refresh();
            return Json(new JsonData { State = AjaxState.Success });
        }

        [Authenticate]
        [HttpPost]
        public ActionResult DeleteCategory(int id)
        {
            XiaoBoKe.CategoryService.Delete(id);
            WebCache.Refresh();
            return Json(new JsonData { State = AjaxState.Success });
        }

        [Authenticate(false)]
        public JsonResult Concern(int id = 0)
        {
            if (id == 0)
            {
                var concern = new ConcernModel { UID = UserSession.AccountId, ConcernUID = CurBlogUserID };
                if (XiaoBoKe.ConcernService.Get(concern) != null)
                {
                    return Json(new JsonData { State = AjaxState.Fail, Message = "您已经关注该用户了！" });
                }
                XiaoBoKe.ConcernService.Add(concern);
                id = concern.ID;
            }
            else
            {
                XiaoBoKe.ConcernService.Delete(id);
            }
            WebCache.Refresh(false, UserSession.AccountId, CurBlogUserID);
            return Json(new JsonData { State = AjaxState.Success, Data = id });
        }

        [TrackRequest]
        public ActionResult UserCenter()
        {
            ViewBag.careMe = WebCache.GetConcernMeUsers(CurBlogUserID);
            ViewBag.careUser = WebCache.GetMyConcernUsers(CurBlogUserID);
            ViewBag.blogUser = WebCache.GetAccount(CurBlogUserID);
            ViewBag.notices = WebCache.GetMyNotices(CurBlogUserID).OrderByDescending(x => x.NoticeTime).ToList();
            return View();
        }
    }
}
